#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <unistd.h>
#include "Task.hpp"
#include "Thread.hpp"
#include "LockGuard.hpp"
#include "log.hpp"

const static int N = 5;

template <class T>
class ThreadPool
{
private:
    ThreadPool(int num = N) : _num(num)
    {
        pthread_mutex_init(&_lock, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    ThreadPool(const ThreadPool<T> &tp) = delete;
    void operator=(const ThreadPool<T> &tp) = delete;

public:
    ~ThreadPool()
    {
        std::cout << "~ThreadPool()" << std::endl;
        // for (auto &it : _threads)
        // {
        //     it.join();
        // }
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }

    static ThreadPool<T> *getinstance()
    {
        if (nullptr == instance) // 提高效率
        {
            LockGuard lockguard(&instance_lock);
            if (nullptr == instance)
            {
                logmessage(DEBUG,"线程单例形成");
                instance = new ThreadPool<T>();
                instance->init();
                instance->start();
            }
        }

        return instance;
    }

    static void DelInstance()
    {
        //std::cout << "DelInstance()" << std::endl;

        LockGuard(getlock());
        if (instance)
        {
            delete instance;
            instance = nullptr;
        }
    }

    class GC
    {
    public:
        GC()
        {
            //std::cout << "GC()" << std::endl;
        }
        ~GC()
        {
            //std::cout << "~GC()" << std::endl;
            DelInstance();
        }
    };

    static GC _gc;

    void ThreadWait()
    {
        pthread_cond_wait(&_cond, &_lock);
    }

    pthread_mutex_t *getlock()
    {
        return &_lock;
    }

    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond);
    }

    void pushtask(const T &t)
    {
        LockGuard lockguard(&_lock); // 保证线程安全
        _tasks.push(t);
        ThreadWakeup(); // 唤醒还在休眠的线程
    }

    T poptask()
    {
        T t = _tasks.front();
        _tasks.pop();
        return t;
    }

    bool IsEmpty()
    {
        return _tasks.empty();
    }

    static void ThreadRoutine(void *args) // 线程走的函数
    {
        ThreadPool *ts = (ThreadPool *)args;
        pthread_detach(pthread_self()); // 线程分离后就不需要等待了
        while (true)
        {
            // 检测有没有任务，有则处理，无则等待
            // 需要访问任务队列，属于临界区需要加锁
            // 维护临界区，出这个区域自动解锁m
            T t;
            {
                LockGuard lockguard(ts->getlock());
                while (ts->IsEmpty())
                {
                    // 任务为空
                    ts->ThreadWait();
                }
                t = ts->poptask();
            }
            t(); // 在临界区外进行任务处理
        }
    }

    void init()
    {
        for (int i = 0; i < _num; i++)
        {
            _threads.push_back(Thread(i, ThreadRoutine, this));
            logmessage(DEBUG,"%d thread running",i);
        }
    }

    void start()
    {
        for (auto &it : _threads)
        {
            //std::cout << "I am ready" << std::endl;
            it.run();
        }
    }

private:
    std::vector<Thread> _threads;
    int _num;
    std::queue<T> _tasks;
    pthread_mutex_t _lock;
    pthread_cond_t _cond;
    static ThreadPool<T> *instance;
    static pthread_mutex_t instance_lock;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::instance_lock = PTHREAD_MUTEX_INITIALIZER;

template <class T>
typename ThreadPool<T>::GC ThreadPool<T>::_gc;